import { hasChanged, isArray, isObject } from "../utils";
import { track, trigger } from "./effect";


// 用一个WeakMap存储已经存在的代理对象
const proxyMap = new WeakMap()
export function reactive(target) {


    // 如果是非数组或者对象直接返回
    if (!isObject(target)) {
        return target
    }
    // 如果传入的已经是代理对象，返回之前代理的对象
    if (isReactive(target)) {
        return target
    }
    // 如果传入的对象和之前的一样，则两个代理对象返回一样的
    if (proxyMap.has(target)) {
        return proxyMap.get(target)
    }
    const proxy = new Proxy(target, {
        get(target, key, receiver) {
            if (key === '__isReactive') {
                return true
            }
            const res = Reflect.get(target, key, receiver)
            // 收集依赖，把依赖放进桶中
            track(target, key)
            // 做了一个懒，如果这个深层对象没有被依赖，就不用代理，依赖了才代理
            return isObject(res) ? reactive(res) : res

        },
        set(target, key, value, receiver) {
            let oldLength = target.length
            const oldValue = target[key]
            const res = Reflect.set(target, key, value, receiver)
            // 如果新值和旧值不一样，则触发trigger
            if (hasChanged(oldValue, value)) {
                // 触发set重新执行这个key的副作用函数
                trigger(target, key)

                // 对数组增删之后，前后的length不一样，手动trigger一次，key为length
                if (isArray(target) && hasChanged(oldLength, target.length)) {
                    trigger(target, 'length')
                }
            }

            return res
        }
    })

    proxyMap.set(target, proxy)
    return proxy
}

export function isReactive(target) {
    return !!(target && target.__isReactive)
}